package com.foreverwin.mes.production.support;

import com.foreverwin.mes.common.enums.HandleEnum;
import com.foreverwin.mes.core.exception.BusinessException;
import com.foreverwin.mes.core.utils.CommonMethods;
import com.foreverwin.mes.core.utils.DateUtil;
import com.foreverwin.mes.core.utils.SpringUtil;
import com.foreverwin.mes.meapi.model.Inventory;
import com.foreverwin.mes.meapi.model.Operation;
import com.foreverwin.mes.meapi.model.Sfc;
import com.foreverwin.mes.meapi.service.InventoryService;
import com.foreverwin.mes.meapi.service.ResrceService;
import com.foreverwin.mes.meapi.service.SfcInWorkService;
import com.foreverwin.mes.production.constant.Constants;
import com.foreverwin.mes.production.dto.ResourceInventoryDto;
import com.foreverwin.mes.production.model.ResourceInventory;
import com.foreverwin.mes.production.model.ResourceInventoryLog;
import com.foreverwin.mes.production.service.ResourceInventoryLogService;
import com.foreverwin.mes.production.service.ResourceInventoryService;
import org.apache.commons.lang3.StringUtils;

import java.util.Date;
import java.util.List;

/**
 * @author Ervin Chen
 * @date 2020/2/4 13:17
 *
 * 上料模式一：针对咖啡豆(一个工单只有一种料)
 * 1.设备是生产设备
 * 2.通过设备找到资源类型，资源类型找到工序；如果工序是清理筛选工序，则需要按照工单bom校验是否可以上料
 * 3.上料时进行校验，工单开始生产不再校验
 * 4.不会进行卸料
 */
public class InventoryIdLoadStrategy implements LoadStrategy {

    private InventoryService inventoryService;
    private ResourceInventoryService resourceInventoryService;
    private ResourceInventoryLogService resourceInventoryLogService;
    private ResrceService resrceService;
    private SfcInWorkService sfcInWorkService;

    private ThreadLocal<Inventory> localStorage = new InheritableThreadLocal<>();

    @Override
    public void initService() {
        inventoryService = SpringUtil.getBean(InventoryService.class);
        resourceInventoryService = SpringUtil.getBean(ResourceInventoryService.class);
        resourceInventoryLogService = SpringUtil.getBean(ResourceInventoryLogService.class);
        resrceService = SpringUtil.getBean( ResrceService.class );
        sfcInWorkService = SpringUtil.getBean( SfcInWorkService.class );
    }

    @Override
    public boolean validate(ResourceInventoryDto resourceInventoryDto) {
        String site = CommonMethods.getSite();
        String resource = resourceInventoryDto.getResrce();
        String itemBo = resourceInventoryDto.getItemBo();
        String inventoryId = resourceInventoryDto.getInventoryId();
        Double loadQty = resourceInventoryDto.getQty();

        if( StringUtils.isBlank( inventoryId ) ){
            throw BusinessException.build("production.resourceInventory.inventoryNotBlank", new Object[]{} );
        }
        if( loadQty == null ){
            throw BusinessException.build( "production.resourceInventory.loadQtyNotBlank", new Object[]{} );
        }
        if( loadQty <= 0 ){
            throw BusinessException.build( "production.resourceInventory.loadQtyNotValid", loadQty );
        }

        //检查设备对应的工序是否为清理筛选工序
        Operation operation = resrceService.selectOperation( site, resource );
        if( operation == null ){
            throw BusinessException.build( "production.resourceInventory.resourceNotExistOperation", resource );
        }
        if( !Constants.OPERATION_CLEAR.equals( operation.getOperation() ) ){
            throw BusinessException.build( "production.resourceInventory.loadOperationNotClear", operation.getOperation() );
        }

        //获取清理筛选工序激活工单，校验上料是否符合工单bom
        List<Sfc> sfcs = sfcInWorkService.selectSfc( HandleEnum.RESOURCE.getHandle( site, resource ) );
        if( sfcs == null || sfcs.isEmpty() ){
            throw BusinessException.build( "production.resourceInventory.resourceNotExistSfcInWork", resource );
        }else{
            resourceInventoryService.validateResourceLoadItemMatchBom( sfcs.get(0).getSfc(), operation.getOperation(), itemBo );
        }
        String shopOrder = HandleEnum.SHOP_ORDER.getPart(sfcs.get(0).getShopOrderBo(), 1);
        resourceInventoryDto.setShopOrder(shopOrder);

        //校验库存编号是否有效
        Inventory queryEntity = new Inventory();
        queryEntity.setInventoryId(inventoryId);
        List<Inventory> inventories = inventoryService.selectList(queryEntity);
        if( inventories.isEmpty() ){
            throw BusinessException.build( "production.resourceInventory.inventoryNotExist", inventoryId );
        }

        //校验库存状态是否可用
        Inventory inventory = inventories.get(0);
        String status = inventory.getStatusBo().split(",")[1];
        if( !Constants.INVENTORY_AVAILABLE_STATUS.equals( status ) ){
            throw BusinessException.build( "production.resourceInventory.inventoryNotAvailable", inventoryId );
        }

        //上料数量是否大于库存现有数量
        Double qtyOnHand = inventory.getQtyOnHand();
        if( loadQty > qtyOnHand ){
            throw BusinessException.build( "production.resourceInventory.loadQtyOverQtyOnHand", loadQty, qtyOnHand );
        }

        //暂存库存
        localStorage.set(inventory);
        return true;
    }

    @Override
    public boolean load(ResourceInventoryDto resourceInventoryDto) {
        String site = CommonMethods.getSite();
        String userBo = CommonMethods.getUserBo();
        String resource = resourceInventoryDto.getResrce();
        String inventoryId = resourceInventoryDto.getInventoryId();
        String vendorLot = resourceInventoryDto.getVendorLot();
        String itemBo = resourceInventoryDto.getItemBo();
        Double qty = resourceInventoryDto.getQty();
        String loadMode = resourceInventoryDto.getLoadMode();
        String shopOrder = resourceInventoryDto.getShopOrder();
        Date now = new Date();

        //扣减库存
        reduceInventory( localStorage.get(), qty );

        //保存设备库存
        String resourceInventoryHandle = HandleEnum.RESOURCE_INVENTORY.getHandle( site, resource, itemBo, shopOrder, inventoryId );
        ResourceInventory resourceInventory = resourceInventoryService.selectById( resourceInventoryHandle );
        if( resourceInventory == null ){
            resourceInventory = new ResourceInventory();
            resourceInventory.setHandle( resourceInventoryHandle );
            resourceInventory.setSite(site);
            resourceInventory.setResrce(resource);
            resourceInventory.setInventoryId(inventoryId);
            resourceInventory.setShopOrder(shopOrder);
            resourceInventory.setItemBo(itemBo);
            resourceInventory.setVendorLot(vendorLot);
            resourceInventory.setOriginalQty(qty);
            resourceInventory.setQtyOnHand(qty);
            resourceInventory.setCreatedDateTime(now);
            resourceInventory.setCreateUserBo(userBo);
            resourceInventoryService.insert(resourceInventory);
        }else{
            resourceInventory.setOriginalQty( resourceInventory.getOriginalQty() + qty );
            resourceInventory.setQtyOnHand( resourceInventory.getQtyOnHand() + qty );
            resourceInventory.setUpdatedDateTime(now);
            resourceInventory.setUpdateUserBo(userBo);
            resourceInventoryService.updateById(resourceInventory);
        }

        //保存上料记录
        String resourceInventoryLogHandle = HandleEnum.RESOURCE_INVENTORY_LOG.getHandle( site, resource, itemBo, shopOrder, DateUtil.format( now ) );
        ResourceInventoryLog resourceInventoryLog = new ResourceInventoryLog();
        resourceInventoryLog.setHandle(resourceInventoryLogHandle);
        resourceInventoryLog.setSite(site);
        resourceInventoryLog.setResrce(resource);
        resourceInventoryLog.setItemBo(itemBo);
        resourceInventoryLog.setInventoryId(inventoryId);
        resourceInventoryLog.setVendorLot(vendorLot);
        resourceInventoryLog.setQty(qty);
        resourceInventoryLog.setLoadMode(loadMode);
        resourceInventoryLog.setCreatedDateTime(now);
        resourceInventoryLog.setCreateUserBo(userBo);
        resourceInventoryLogService.insert(resourceInventoryLog);

        return true;
    }

    public boolean reduceInventory( Inventory inventory, Double qty ){
        inventory.setQtyOnHand( inventory.getQtyOnHand() - qty );
        return inventoryService.updateById( inventory );
    }
}
